package appSimulator;

import java.util.Random;
import java.util.Timer;

import scheduler.SchedulerTask;

import monitor.MonitorTask;

import environment.Application;
import environment.Environment;
import environment.PhysicalMachine;
import environment.VirtualMachine;

public class Simulator {
	
	public static void main(String[] args) throws Exception {
		new Simulator().start();
	}
	
	public Simulator() throws Exception
	{
		createTestEnvironment();
		startScheduling();
	}
	
	private void createTestEnvironment()
	{
		/* initialize environment */
		
		// physical machine one
		PhysicalMachine pm1 = new PhysicalMachine(1, 1500);
		pm1.addVirtualMachine(new VirtualMachine(Environment.getIncrementedVMCounter(), 600));
		pm1.addVirtualMachine(new VirtualMachine(Environment.getIncrementedVMCounter(), 200));
		pm1.start();
		
		// physical machine two
		PhysicalMachine pm2 = new PhysicalMachine(2, 2500);
		pm2.addVirtualMachine(new VirtualMachine(Environment.getIncrementedVMCounter(), 450));
		pm2.addVirtualMachine(new VirtualMachine(Environment.getIncrementedVMCounter(), 100));
		pm2.start();
		
		PhysicalMachine pm3 = new PhysicalMachine(3, 2000);
		
		PhysicalMachine pm4 = new PhysicalMachine(4, 2000);
		
		PhysicalMachine pm5 = new PhysicalMachine(5, 2000);
		
		Environment.physicalMachines.add(pm1);
		Environment.physicalMachines.add(pm2);
		Environment.physicalMachines.add(pm3);
		Environment.physicalMachines.add(pm4);
		Environment.physicalMachines.add(pm5);
	}
	
	private void startScheduling() throws Exception
	{
		// monitor and scheduler
		Timer timer = new Timer();
		// monitor --> delay 1 second, period 2 seconds
		timer.schedule(new MonitorTask(), 1000, 2000);
		// scheduler --> delay 0 seconds, period 2 seconds
		timer.schedule(new SchedulerTask(), 0, 2000);
	}
	
	public void start() throws Exception
	{
		// add apps
		JMSProducer jmsProducer = new JMSProducer();
		
		Random random = new Random();
		int currentCycle = 0;
		int appId=1;
		while(currentCycle<20)
		{
			int appsToGenerate = random.nextInt(8)+3;
			
			for(int i=0; i <= appsToGenerate ; i++)
			{
				 Application.Type appType =  Application.Type.values()[random.nextInt(3)];
				 jmsProducer.sendMessage(new Application(appId++, appType));
			}
			
			/* max. 3000 ms */
			Thread.sleep(random.nextInt(6000));
			currentCycle++;
		}
		
		jmsProducer.close();
	}
}
